package main

import (
	"fmt"
	"github.com/fatih/structs"
	"github.com/gookit/goutil/dump"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"store_appoint_keys_to_redis/store_data_to_redis"
	"time"
)

// Notice 使用structs包将结构体转为map
// Notice 需要注意，structs 标签的值要跟json标签的值一样，否则从redis中读数据的时候会有问题
// Notice 这样做有一个限制：就是后面再想使用structs包将结构体转map的话，如果使用同一个User结构体，createAt与updateAt这2个字段一直不会出现在被转的map中
type User struct {
	ID          int       `json:"id" gorm:"primaryKey;column:id" structs:"id"`
	Name        string    `json:"name" gorm:"column:name" structs:"name"`
	Email       string    `json:"email" gorm:"column:email" structs:"email"`
	PhoneNumber string    `json:"phoneNumber" gorm:"phone_number" structs:"phoneNumber"`
	CreateAt    time.Time `json:"createAt" gorm:"column:create_at;default:null" structs:"-"`
	UpdateAt    time.Time `json:"updateAt" gorm:"column:update_at;default:null" structs:"-"`
}

func main() {
	dsn := "root:123@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic(err)
	}
	fmt.Println("db: ", db)

	// Notice 假如实际中 create_at、update_at 这2个字段没有用处，直接不查询这2个字段
	result := make([]*User, 0)

	err = db.Table("user").Select("id", "name", "email", "phone_number").Find(&result).Error
	if err != nil {
		panic(err)
	}

	dump.P(result) // 数据库中有2条数据，这样的到的结果还是会有CreateAt与UpdateAt
	/*
		[]*main.User [ #len=2
		  &main.User {
		    ID: int(1),
		    Name: string("naruto"), #len=6
		    Email: string("123@qq.com"), #len=10
		    PhoneNumber: string("13333333333"), #len=11
		    CreateAt: time.Time {
		      wall: uint64(0),
		      ext: int64(0),
		      loc: *time.Location<nil>,
		    },
		    UpdateAt: time.Time {
		      wall: uint64(0),
		      ext: int64(0),
		      loc: *time.Location<nil>,
		    },
		  },
		  &main.User {
		    ID: int(2),
		    Name: string("sasuke"), #len=6
		    Email: string("222@qq.com"), #len=10
		    PhoneNumber: string("16666666666"), #len=11
		    CreateAt: time.Time {
		      wall: uint64(0),
		      ext: int64(0),
		      loc: *time.Location<nil>,
		    },
		    UpdateAt: time.Time {
		      wall: uint64(0),
		      ext: int64(0),
		      loc: *time.Location<nil>,
		    },
		  },
		]
	*/

	// 结构体转map
	sliceMapRet := make([]map[string]interface{}, 0)

	for _, item := range result {
		currMp := structs.Map(item)
		sliceMapRet = append(sliceMapRet, currMp)
	}
	dump.P(sliceMapRet)
	// Notice 因为 createAt与updateAt这2个字段在structs标签中做了忽略处理,所以转换后的map不会有这2个字段
	/*
		[]map[string]interface {} [ #len=2
			  map[string]interface {} { #len=4
			    "id": int(1),
			    "name": string("naruto"), #len=6
			    "email": string("123@qq.com"), #len=10
			    "phoneNumber": string("13333333333"), #len=11
			  },
			  map[string]interface {} { #len=4
			    "id": int(2),
			    "name": string("sasuke"), #len=6
			    "email": string("222@qq.com"), #len=10
			    "phoneNumber": string("16666666666"), #len=11
			  },
			],
	*/

	// 最后使用pipeline写入到redis中即可
	errStore := store_data_to_redis.StoreUsersToRedis(sliceMapRet)
	if errStore != nil {
		fmt.Println("errStore: ", errStore)
	} else {
		fmt.Println("用户数据保存到redis成功!!!")
	}
}
